# coding: utf-8
from io import BytesIO
from typing import List

from PIL import Image
from PIL.ImageQt import toqpixmap
from PySide6.QtCore import Signal, Qt, QUrl, QPropertyAnimation, QEasingCurve, QPoint, QSize
from PySide6.QtGui import QPainter, QColor, QPixmap, QResizeEvent, QShowEvent
from PySide6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
from PySide6.QtWidgets import QHBoxLayout, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QVBoxLayout, \
    QListWidgetItem
from loguru import logger
from qfluentwidgets import TransparentToolButton, FluentIcon, isDarkTheme, SmoothScrollDelegate, BodyLabel, ListWidget, \
    setFont, SimpleCardWidget

from ...common import APIBase, ChapterPhotoModel, BookItemModel
from ...components import queue_thread_manager


class BottomToolBar(SimpleCardWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.horizontalLayout = QHBoxLayout(self)
        self.chapterBtn = TransparentToolButton(FluentIcon.MENU, self)
        self.prevBtn = TransparentToolButton(FluentIcon.LEFT_ARROW, self)
        self.nextBtn = TransparentToolButton(FluentIcon.RIGHT_ARROW, self)

        self.setFixedHeight(50)
        self.horizontalLayout.addWidget(self.chapterBtn)
        self.horizontalLayout.addWidget(self.prevBtn)
        self.horizontalLayout.addWidget(self.nextBtn)

    def _normalBackgroundColor(self):
        c = 0 if isDarkTheme() else 255
        return QColor(c, c, c, 150)


class ChapterListWidget(SimpleCardWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.verticalLayout = QVBoxLayout(self)
        self.titleLabel = BodyLabel('书名', self)
        self.listWidget = ListWidget(self)
        self.animation = QPropertyAnimation(self, b'pos', self)

        setFont(self.titleLabel, 24)
        self.titleLabel.setContentsMargins(15, 10, 10, 10)
        self.setFixedWidth(300)

        self.verticalLayout.setAlignment(Qt.AlignmentFlag.AlignTop)
        self.verticalLayout.addWidget(self.titleLabel)
        self.verticalLayout.addWidget(self.listWidget)

        self.animation.setEasingCurve(QEasingCurve.Type.InOutQuart)
        self.animation.setDuration(200)

    def setTitle(self, title: str):
        self.titleLabel.fontMetrics().elidedText(title, Qt.TextElideMode.ElideRight, 200)
        self.titleLabel.setText(title)

    def addModel(self, model: BookItemModel):
        item = QListWidgetItem(model.title)
        item.setSizeHint(QSize(200, 40))
        item.setData(Qt.ItemDataRole.UserRole, model.photo_url)
        self.listWidget.addItem(item)

    def setCurrentIndex(self, index: int):
        self.listWidget.setCurrentRow(index)

    def showEvent(self, event: QShowEvent):
        self.animation.setStartValue(QPoint(self.x() - self.width() - 10, self.y()))
        self.animation.setEndValue(QPoint(10, self.y()))
        self.animation.start()

    def hideEvent(self, event):
        self.animation.setStartValue(QPoint(10, self.y()))
        self.animation.setEndValue(QPoint(self.x() - self.width() - 10, self.y()))
        self.animation.start()
        self.hide()

    def _normalBackgroundColor(self):
        c = 0 if isDarkTheme() else 255
        return QColor(c, c, c, 150)


class PhotosInterface(QGraphicsView):
    closed = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.items = []  # type: list[QGraphicsPixmapItem]
        self.y_offset = 0
        self.closeBtn = TransparentToolButton(FluentIcon.RETURN, self)
        self.graphicsScene = QGraphicsScene(self)
        self.scrollDelagate = SmoothScrollDelegate(self)
        self.manager = QNetworkAccessManager(self)

        self.bottomToolBar = BottomToolBar(self)
        self.leftToolBar = ChapterListWidget(self)

        self.setScene(self.graphicsScene)
        self.manager.finished.connect(self._onFinished)

        self.__initWidgets()

    def __initWidgets(self):
        self.setObjectName('PhotosInterface')
        self.closeBtn.setGeometry(5, 5, 40, 36)
        self.closeBtn.clicked.connect(self.closed)
        self.setViewportMargins(0, 45, 0, 0)
        self.setCacheMode(QGraphicsView.CacheModeFlag.CacheBackground)
        self.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignHCenter)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.setRenderHints(QPainter.RenderHint.Antialiasing | QPainter.RenderHint.SmoothPixmapTransform)

        qss = 'background-color: transparent; border: none; outline: none;'
        self.setStyleSheet(qss)
        self.__connectSignals()

        self.leftToolBar.hide()

    def __connectSignals(self):
        self.closed.connect(self.clear)

        self.bottomToolBar.chapterBtn.clicked.connect(self.onChapterClicked)
        self.bottomToolBar.prevBtn.clicked.connect(self.onPrevClicked)
        self.bottomToolBar.nextBtn.clicked.connect(self.onNextClicked)

        self.leftToolBar.listWidget.itemClicked.connect(self.onItemClicked)

        self.installEventFilter(self)

    def loadPhoto(self, obj: APIBase, url: str, models: List[BookItemModel]=None):
        if models:
            self.leftToolBar.setTitle(obj.name)
            self.setProperty('models', models)
            for i, md in enumerate(models):
                self.leftToolBar.addModel(md)
                if md.photo_url == url:
                    self.leftToolBar.setCurrentIndex(i)
            self.setProperty('source', obj)
        queue_thread_manager.send_function(obj.photos, url, slot=self.loadPhotoFinished)

    def loadPhotoFinished(self, model: ChapterPhotoModel):
        width = model.width
        min_height = model.min_height
        headers = model.source.headers  # type: dict
        urls = model.urls

        self.setProperty('width', width)
        self.setProperty('urls', urls)

        for url in urls:
            pixmap = QPixmap(width, min_height)
            pixmap.fill(Qt.GlobalColor.transparent)
            item = QGraphicsPixmapItem(pixmap)
            self.items.append(item)
            self.graphicsScene.addItem(item)
            item.setPos(0, self.y_offset)
            self.y_offset += pixmap.height()

            request = QNetworkRequest(QUrl(url))
            for key, value in headers.items():
                request.setRawHeader(key.encode(), value.encode())
            self.manager.get(request)

    def _onFinished(self, reply: QNetworkReply):
        if reply.error() == QNetworkReply.NetworkError.NoError:
            file_bytes = BytesIO(reply.readAll().data())
            img = Image.open(file_bytes)
            pixmap = toqpixmap(img)
            url = reply.url().toString()
            urls = self.property('urls')
            index = urls.index(url)
            item = self.items[index]
            width = self.property('width')
            pixmap = pixmap.scaledToWidth(width, Qt.TransformationMode.SmoothTransformation)
            item.setPixmap(pixmap)
        else:
            logger.error(f'Network error: {reply.error()}, {reply.errorString()}')
        reply.deleteLater()

        y = 0
        for item in self.items:
            item.setPos(0, y)
            y += item.pixmap().height()

    def clear(self):
        for item in self.items:
            self.graphicsScene.removeItem(item)
        self.graphicsScene.clear()
        self.graphicsScene.setSceneRect(0, 0, 0, 0)
        self.items.clear()
        self.y_offset = 0
        self.verticalScrollBar().setValue(0)

    def resizeEvent(self, event: QResizeEvent):
        super().resizeEvent(event)
        self.bottomToolBar.setGeometry(10, self.height() - 60, self.width() - 20, 50)
        self.leftToolBar.setGeometry(10, 55, self.width(), self.height() - 120)

    # def eventFilter(self, obj: QObject, event: QEvent):
    #     modifiers = QApplication.keyboardModifiers()
    #     # 捕捉鼠标滚轮事件
    #     if modifiers == Qt.KeyboardModifier.ControlModifier:
    #         if event.type() == QEvent.Type.Wheel:
    #             event: QWheelEvent
    #             self.setTransformationAnchor(self.ViewportAnchor.AnchorUnderMouse)
    #             x = event.angleDelta().x()
    #             y = event.angleDelta().y()
    #             if x == 0 and y != 0:
    #                 if y < 0:
    #                     self.scale(0.95, 0.95)
    #                 else:
    #                     self.scale(1.05, 1.05)
    #             else:
    #                 if x < 0:
    #                     self.scale(0.95, 0.95)
    #                 else:
    #                     self.scale(1.05, 1.05)
    #
    #         return True
    #     return super().eventFilter(obj, event)

    def onChapterClicked(self):
        if self.leftToolBar.isVisible():
            self.leftToolBar.hide()
        else:
            self.leftToolBar.show()

    def onPrevClicked(self):
        pass

    def onNextClicked(self):
        current_row = self.leftToolBar.listWidget.currentRow()
        print(current_row)
        # self.leftToolBar.listWidget.setCurrentRow(0)

    def onItemClicked(self, item: QListWidgetItem):
        self.clear()
        url = item.data(Qt.ItemDataRole.UserRole)
        source = self.property('source')
        self.loadPhoto(source, url)